package com.itfreer.utils.hibernate;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;

/**
 * 定义查询参数转换类
 */
public class PredicateConvertUtils {
	
	/**
	 * 参数转换
	 * 
	 * id = 1 and name = 'a' : {id:1,name:'a'}
	 * (id=1 and name='a') or (id=2 and name='b') : {or:[{id:1,name:'a'},{id:2,name:'b'}]}
	 * (id=1 or name='a') and (id=2 or name='b') : {and:[{or:[{id:1},{name:'a'}]},{or:[{id:2},{name:'b'}]}]}
	 * @param crit
	 * @param where
	 */
	public static void convert(Criteria crit, Map<String, Object> where) {
		// 条件为空，返回
		if (where == null || where.size() <= 0) {
			return;
		}
		Criterion criterion = getCriterions(where);
		crit.add(criterion);
	}

	/**
	 * 参数转换
	 * 
	 * @param where
	 */
	@SuppressWarnings("unchecked")
	private static Criterion getCriterions(Map<String, Object> where) {
		Set<String> keys = where.keySet();
		if(keys.size()<=1){
			// 小于等于1的时候，存在3种情况
			String[] fieldMsg = (String[])keys.toArray(new String[keys.size()]);
			// 取第一个参数
			String[] fields = fieldMsg[0].split(":");
			String field = null;
			String option = null;
			if (fields.length == 2) {
				field = fields[0];
				option = fields[1];
			} else {
				field = fieldMsg[0];
				option = "=";
			}
			Object value = where.get(fieldMsg[0]);
			
			// 如果是or操作符
			if (field.trim().toLowerCase().equals("or")) {
				List<Map<String, Object>> wheres = (List<Map<String, Object>>)value;
				Criterion[] criterions = new Criterion[wheres.size()];
				int i = 0;
				for(Map<String, Object> item : wheres){
					criterions[i] = getCriterions(item);
					i++;
				}
				Criterion criterion = Restrictions.or(criterions);
				return criterion;
			} else if (field.trim().toLowerCase().equals("and")) {
				// 如果是and操作符
				List<Map<String, Object>> wheres = (List<Map<String, Object>>)value;
				Criterion[] criterions = new Criterion[wheres.size()];
				int i = 0;
				for(Map<String, Object> item : wheres){
					criterions[i] = getCriterions(item);
					i++;
				}
				Criterion criterion = Restrictions.and(criterions);
				return criterion;
			} else {
				// 如果只是简单对象
				return getSimpleCriterion(field, option, value);
			}
		} else {
			// 如果存在多个，说明非or或and操作
			List<Criterion> criterions = getLastCriterion(where);
			if(criterions==null){
				return null;
			}
			Criterion[] c = (Criterion[])criterions.toArray(new Criterion[criterions.size()]);
			Criterion criterion = Restrictions.and(c);
			return criterion;
		}
	}
	
	/**
	 * 获取最底一层的查询条件
	 * @param where
	 * @return
	 */
	private static List<Criterion> getLastCriterion(Map<String, Object> where){
		// 条件为空，返回
		if (where == null || where.size() <= 0) {
			return null;
		}

		List<Criterion> result = new ArrayList<Criterion>();
		Set<String> keys = where.keySet();
		for (String key : keys) {
			// 基本参数分析
			String[] fields = key.split(":");
			String field = null;
			String option = null;
			if (fields.length == 2) {
				field = fields[0];
				option = fields[1];
			} else {
				field = key;
				option = "=";
			}
			Object value = where.get(key);

			if (field.trim().toLowerCase().equals("or") || field.trim().toLowerCase().equals("and")) {
				// 如果是or或是and操作符，抛出异常
				throw new RuntimeException("查询条件转换算法异常！");
			} else {
				Criterion criterion = getSimpleCriterion(field, option, value);
				if(criterion!=null){
					result.add(criterion);
				}
			}
		}
		return result;
	}

	/**
	 * 获取简单的对象
	 * @param field		字段
	 * @param option	操作符
	 * @param value		值
	 * @return
	 */
	private static Criterion getSimpleCriterion(String field, String option, Object value) {
		Criterion result = null;
		if (option.equals("=")) {
			result = Restrictions.eq(field, value);
		} else if (option.equals("!=")) {
			result = Restrictions.not(Restrictions.eq(field, value));
		} else if (option.equals(">")) {
			result = Restrictions.gt(field, value);
		} else if (option.equals(">=")) {
			result = Restrictions.ge(field, value);
		} else if (option.equals("<")) {
			result = Restrictions.lt(field, value);
		} else if (option.equals("<=")) {
			result = Restrictions.le(field, value);
		} else if (option.equals("in")) {
			Object[] values = value.toString().split(",");
			result = Restrictions.in(field, values);
		} else if (option.equals("nin")) {
			Object[] values = value.toString().split(",");
			result = Restrictions.not(Restrictions.in(field, values));
		} else if (option.equals("isnull")) {
			Property property = Property.forName(field);
			result = property.isNull();
		} else if (option.equals("isnnull")) {
			Property property = Property.forName(field);
			result = property.isNotNull();
		} else if (option.equals("like")) {
			result = Restrictions.like(field, "%"+value+"%");
		} else if (option.equals("%like")) {
			result = Restrictions.like(field, "%"+value);
		} else if (option.equals("like%")) {
			result = Restrictions.like(field, value+"%");
		} else if (option.equals("notlike")) {
			result = Restrictions.sqlRestriction("(" + field + " not like '%" + value + "%' or " + field + " is null )");
		} else if (option.equals("%notlike")) {
			result = Restrictions.sqlRestriction("(" + field + " not like '%" + value + "' or " + field + " is null)");
		} else if (option.equals("notlike%")) {
			result = Restrictions.sqlRestriction("(" + field + " not like '" + value + "%' or " + field + " is null)");
		} else {
			throw new RuntimeException("不支持的操作符【" + option + "】！");
		}
		return result;
	}

}